package com.surrealbananapeel.battleship;

import java.util.Random;

/**
 * This is the class for holding a ship. It include such things as the ships 
 * orientation, name, and points.
 * 
 * @author Emmett Little and Alberto Saavedra
 */
public class Ship
{
    public static enum Orientation {XY, XZ, YZ};
    
    private Orientation orientation;
    private String name;
    private Point[] points;
    
    /**
     * Constructor to create a new ship from an old ship.
     * 
     * @param ship The ship to copy
     */
    public Ship(Ship ship)
    {
        this(ship.toString());
    }
    
    /**
     * Create a ship from a string describing the ship.
     * 
     * @param ship The ship string
     */
    public Ship(String ship)
    {
        String[] namePoint = ship.split(":");
        String[] point = namePoint[1].split(";");
        
        this.name = namePoint[0];
        
        this.points = new Point[point.length];
        for (int i=0; i<point.length; i++)
            this.points[i] = new Point(point[i]);
        this.orientation = Orientation.XY;
    }
    
    /**
     * Shift the boat by the supplied amount. If the ship is successful then 
     * true is returned, otherwise false is returned.
     * 
     * @param x The amount to shift the x coordinate
     * @param y The amount to shift the y coordinate
     * @param z The amount to shift the z coordinate
     * @return True if the shift was successful, false otherwise
     */
    public boolean shift(int x, int y, int z)
    {
        boolean result = true;
        
        for (int i=0; i<points.length && result; i++)
        {
            int px = points[i].getX() + x;
            int py = points[i].getY() + y;
            int pz = points[i].getZ() + z;
            
            if (px < 0 || px >= BattleshipClient.WIDTH || 
                    py < 0 || py >= BattleshipClient.HEIGHT || 
                    pz < 0 || pz >= BattleshipClient.DEPTH)
                result = false;
        }
        if (result)
        {
            for (int i=0; i<points.length && result; i++)
            {
                points[i].addX(x);
                points[i].addY(y);
                points[i].addZ(z);                
            }
        }
        return result;
    }
    
    /**
     * Get the name of the ship.
     * 
     * @return The name of the ship
     */
    public String getName()
    {
        return name;
    }
    
    /**
     * Get the points of the ship.
     * 
     * @return The points of the ship
     */
    public Point[] getPoints()
    {
        return points;
    }
    
    /**
     * Get the orientation of the ship.
     * 
     * @return The orientation of the ship.
     */
    public Orientation getOrientation()
    {
        return orientation;
    }
    
    /**
     * Update the orientation of the ship.
     * 
     * @param o The new orientation of the ship
     */
    public void updateOrientation(Orientation o)
    {
        if (orientation == Orientation.XY)
        {
            if (o == Orientation.XZ)
            {
                for (int i=0; i<points.length; i++)
                {
                    points[i].swap(false, true, true);
                }
            }
            else if (o == Orientation.YZ)
            {
                for (int i=0; i<points.length; i++)
                {
                    points[i].swap(true, false, true);
                }
            }
        }
        else if (orientation == Orientation.XZ)
        {
            if (o == Orientation.XY)
            {
                for (int i=0; i<points.length; i++)
                {
                    points[i].swap(false, true, true);
                }
            }
            else if (o == Orientation.YZ)
            {
                for (int i=0; i<points.length; i++)
                {
                    points[i].swap(true, true, false);
                }
            }
        }
        else
        {
            if (o == Orientation.XY)
            {
                for (int i=0; i<points.length; i++)
                {
                    points[i].swap(true, false, true);
                }
            }
            else if (o == Orientation.XZ)
            {
                for (int i=0; i<points.length; i++)
                {
                    points[i].swap(true, true, false);
                }
            }
        }
    }
    
    /**
     * Randomly rotate and shift the ship.
     */
    public void randomize()
    {
        Random rand = new Random();
        switch(rand.nextInt(3))
        {
            case 0:
                updateOrientation(Orientation.XY);
                break;
            case 1:
                updateOrientation(Orientation.XZ);
                break;
            case 2:
                updateOrientation(Orientation.YZ);
                break;
        }
        while(!shift(rand.nextInt(BattleshipClient.WIDTH), 
                rand.nextInt(BattleshipClient.HEIGHT), 
                rand.nextInt(BattleshipClient.DEPTH)));
    }
    
    /**
     * Checks if the current ship is intersecting with the supplied ship. An 
     * integer is returned for each overlapping point.
     * 
     * @param s The ship to check intersections with
     * @return An integer representing the number of overlapping points
     */
    public int intersect(Ship s)
    {
        int result = 0;
        for (int i=0; i<points.length; i++)
        {
            for (int j=0; j<s.getPoints().length; j++)
            {
                if (points[i].equals(s.getPoints()[j]))
                {
                    result++;
                    break;
                }
            }
        }
        return result;
    }
    
    /* (non-Javadoc)
     * @see java.lang.Object#toString()
     */
    @Override
    public String toString()
    {
        String result = getName()+":";
        for (int i=0; i<points.length; i++)
        {
            result += points[i].toString();
            if (i != points.length-1)
                result += ";";
        }
        return result;
    }
}
